from __future__ import annotations
import json
from typing import Union, Callable
from frame_structure import Frame, ElementSchema, BaseContainer, SingleContainer, SetContainer, ListContainer, Ontology
from frame_script import FRAME_SCRIPT, DEFAULT_SCRIPT
import script_lib

class FrameManager:
    def __init__(self, frame_filepath: str, owl_filepath: str) -> None:
        self.frame_name_map: dict[str, dict] = {}
        self.frame_script_map: dict[str, dict[str, Callable]] = {}
        self.marker_map: dict[str, Union[Frame, Ontology]] = {}
        self.marker_map_primary: dict[str, Frame] = {}
        self.marker_map_prototype: dict[str, Frame] = {}
        self._counter = 0

        with open(frame_filepath, 'r', encoding='utf-8') as f:
            frames_info = json.loads(f.read())
            for frame_info in frames_info:
                frame_name, frame = self.parse_frame_info(frame_info)
                self.frame_name_map[frame_name] = frame

        for frame_name, script_map in FRAME_SCRIPT.items():
            _script_map: dict[str, Callable] = {**DEFAULT_SCRIPT, **script_map}
            self.frame_script_map[frame_name] = _script_map

    @staticmethod
    def parse_frame_info(frame_info: dict) -> tuple[str, dict]:
        frame_name = frame_info['name']
        frame = {
            'name': frame_name,
            'tag': frame_info['tag'],
            'lexis': frame_info['awakenLexis'],
            'elements': {}
        }
        for element_info in frame_info['element']:
            element_name = element_info['name']
            is_core_element = element_name in frame_info['coreElement']
            type_restraint = element_info['type']
            if element_info['container'] == 'single':
                if 'base' in element_info['type']:
                    element_schema = ElementSchema(element_name, is_core_element, type_restraint, BaseContainer)
                else:
                    element_schema = ElementSchema(element_name, is_core_element, type_restraint, SingleContainer)
            elif element_info['container'] == 'set':
                element_schema = ElementSchema(element_name, is_core_element, type_restraint, SetContainer)
            elif element_info['container'] == 'list':
                element_schema = ElementSchema(element_name, is_core_element, type_restraint, ListContainer)
            else:
                raise TypeError
            frame['elements'][element_name] = element_schema
        return (frame_name, frame)

    def clear_marker(self) -> None:
        self.marker_map = {}
        self.marker_map_primary = {}
        self.marker_map_prototype = {}

    def get_frames_from_file(self, file_path: str) -> list[Frame]:
        frames = []
        with open(file_path, 'r', encoding='gb18030') as f:
            data_list = json.load(f)
            for data in data_list:
                frame = Frame(self, data['frame']).create_from_dict(data)
                frames.append(frame)
        return frames
